#include "CommonDef.hlsli"

struct GSOutput
{
    float4 pos : SV_POSITION;
};


cbuffer cbPerFrame: register(b0)
{
    float3 initialWorldPos;
    //in seconds
    float g_TimeElapsed;
    float g_gameTime;
};

cbuffer cbFixed: register(b1)
{
    float g_StartLifetime;
};

Texture1D RandomTexture;
SamplerState LinearSampler;

static const int kBurstUnit = 1;

float4 RandomVec(float2 offset)
{
    return RandomTexture.SampleLevel(
        LinearSampler, float2(g_TimeElapsed, g_TimeElapsed) + offset, 0);
}

[maxvertexcount(32)]
void main(
    point Particle inputParticles[1],
    inout PointStream<Particle> particles
)
{
    Particle inputParticle = inputParticles[0];
    //particles.Append(inputParticle);
    if (inputParticle.type == PARTICLE_TYPE_EMIT)
    {
        float timeSinceLastGen = inputParticle.currentLifetime + g_TimeElapsed;
        if (timeSinceLastGen < PARTICLE_GEN_INTERVAL)
        {
            inputParticle.currentLifetime = timeSinceLastGen;
            particles.Append(inputParticle);
            return;
        }
       // float bias = 0.000001f;
        int generated = floor(timeSinceLastGen / PARTICLE_GEN_INTERVAL); // 调用的一开始就会生成一个
        int dead = max(0.0f, floor((timeSinceLastGen - g_StartLifetime) / PARTICLE_GEN_INTERVAL));
        int survivedBatchCount = generated - dead;
     
        float lifetimeLeft = (generated) * PARTICLE_GEN_INTERVAL + g_StartLifetime - timeSinceLastGen;
        //从后向前推
        for (int i = 0; i < survivedBatchCount; ++i)
        {
            Particle emitted;
            emitted.initialPos = float4(initialWorldPos, 0.0f);
            emitted.size = 3.0f.xx;
            //currentLifetime 是剩下的存活时间
            emitted.currentLifetime = lifetimeLeft;
            emitted.type = PARTICLE_TYPE_NORMAL;
            for (int j = 0; j < kBurstUnit; ++j)
            {
                float4 randomed = RandomVec(float2(i, j));
                emitted.initialVel = 3 * randomed;
                particles.Append(emitted);
            }
            lifetimeLeft -= PARTICLE_GEN_INTERVAL;
        }
        float timeLeft = generated * PARTICLE_GEN_INTERVAL - timeSinceLastGen;
        inputParticle.currentLifetime = timeLeft;
        particles.Append(inputParticle);
    }
    else
    {
        inputParticle.currentLifetime -= g_TimeElapsed;
        if (inputParticle.currentLifetime > 0.0f)
        {
            particles.Append(inputParticle);
        }
    }
}